`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////Asyncsys Lab////////////////////////////////////////
// Author: Zhenbang Kang
// Email: kangzhb20@lzu.edu.cn
// Create Date: 2022/06/10 
// Module Name: DW8051_updn_ctr_biu
// Project Name: ac8051 (Asynchronous Click 8051)
// Target Devices: XC7A100TFGG484-2
// Tool Versions: Vivado 2019.1
// Description:BIU counter
// Revision: V2.0
//////////////////////////////////////////////////////////////////////////////////

module DW8051_updn_ctr_biu    (data,
                           up_dn,
                           load,
                           cen,
                           fire,
                           reset,
                           count,
                           tercnt
			   );
 parameter width = 3;
 //load from controller set_pc_n , cen from controller inc_pc.
 //these signals decided the pc increase or not.
 input [2:0] data;
 input up_dn;
 input load;
 input cen;
 input fire;
 input reset;
 output [2:0] count;
 output tercnt;

//------------------------------------------------------------------------------
(* dont_touch = "true" *)wire [2:0]data;
(* dont_touch = "true" *)wire up_dn;
(* dont_touch = "true" *)wire load;
(* dont_touch = "true" *)wire cen;
wire reset;
(* dont_touch = "true" *)wire [2:0] count;
(* dont_touch = "true" *)wire tercnt;
(* dont_touch = "true" *)wire [2:0] max_count;
(* dont_touch = "true" *)wire fire;
//---------------
// local signals:
//---------------
(* dont_touch = "true" *)reg [2:0] ctr_state;
(* dont_touch = "true" *)wire [2:0] next_state;
 
//------------------------------------------------------------------------------

  assign max_count = ( 1 << 3) - 1;

  assign next_state = (load == 0) ? data : 
		      ((cen == 0) ? ctr_state :
		      ((up_dn == 1) ? (ctr_state + 1) : (ctr_state - 1)));
  
  always @(posedge fire or negedge reset)
    if (!reset)
      ctr_state <= 0;
    else
      ctr_state <= next_state;

  assign  count  = ctr_state;
  assign tercnt = ((up_dn == 1 && ctr_state == max_count) ||
		   (up_dn == 0 && ctr_state == 0)) ? 1 : 0;
endmodule

